package com.dhcc.DRGsHosp.facade.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.inject.Named;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openkoala.koala.commons.InvokeResult;
import org.openkoala.koalacommons.resourceloader.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.dhcc.DRGsHosp.application.DrgFeeMedinsApplication;
import com.dhcc.DRGsHosp.core.domain.Department;
import com.dhcc.DRGsHosp.core.domain.DrgFeeMedinsDetail;
import com.dhcc.DRGsHosp.facade.DrgFeeMedinsFacade;
import com.dhcc.DRGsHosp.facade.dto.IndexCalDTO;
import com.dhcc.DRGsHosp.facade.impl.assembler.IndexCalAssembler;
import com.dhcc.DRGsHosp.infra.util.DrgsIndex;
import com.dhcc.DRGsHosp.infra.util.MonitorResultUtil;


/**
 * @title		:DrgFeeMedinsFacadeImpl.java
 * @description	:
 * @author		:huangju
 * @date		:2018年12月06日
 */
@Named("DrgFeeMedinsFacade")
public class DrgFeeMedinsFacadeImpl implements DrgFeeMedinsFacade {

	@Autowired
	private DrgFeeMedinsApplication drgFeeMedinsApplication;
	
	private StringBuffer message = new StringBuffer() ;//返回前台的信息
    
    private Float percent = new Float(0);//进度完成百分比
    
    private String detail="";//进度进行详情
    
    private String time="";
    
    private long mdStartTime=0;
    
    private String stateInfo="";//状态信息 error-错误  done-完成一个  finish-结束
/**
 * 北京drg支付医保分组结果数据上传
 * huangju
 */
@Override
public InvokeResult importDrgFeeMedinsData(String filePath ,String type) {  
	try {
        message = new StringBuffer("") ;
        detail="";
        percent = 0F ;
        stateInfo = "0" ;
        message.append("准备解析 ，请稍等！<br>") ;
        Row row = null ;
        Sheet sheet = readExcelSheet(filePath,0) ;
        int rowNum=sheet.getLastRowNum();//行数
        message.setLength(0);
        message.append("正在解析文件    "+filePath.substring(filePath.lastIndexOf("\\")+1) + "<br>");
        if(rowNum==0){
            //excel为空的情况
            message.append( "excel中数据为空<br> ") ;
            stateInfo="2";
        }else{
            for (int i = 1; i <= rowNum; i++) {
                row=sheet.getRow(i);
                // 该行为空时解析下一行
                if(null == row) {
                    message.append( "第" + (i+1) +"行数据为空，跳过<br> ") ;
                    continue ;
                }
                //三张科室成本数据相关表分别进行导入
                if("uploadybFuFeiDetail".equals(type)){
                    DrgFeeMedinsDetail entity = new DrgFeeMedinsDetail() ;  
                    percent=(float)i*100/(float)rowNum;
                    printProgress(rowNum,i) ;
                    for (int j = 0; j < 47 ; j++) {
                        String value = getCellValue(row.getCell(j))==null?"":getCellValue(row.getCell(j)) ;
                        switch(j) {
                            // 医院编码
                            case 0 : entity.setHosp_code(value); break;
                            // 医院名称
                            case 1 : entity.setHosp_name(value); break;
                            //终端机编号
                            case 2 : entity.setTerminal_no(value); break;
                            //险种
                            case 3 : entity.setInsur_type(value); break;
                            //病案号
                            case 4 : entity.setMr_no(value); break;
                            //姓名
                            case 5 : entity.setPname(value); break;
                            //年龄
                            case 6 : entity.setPage(Integer.parseInt(value)); break;
                            //入院日期
                            case 7 : entity.setIn_date(MonitorResultUtil.objectToDate(value)); break;
                            //出院日期
                            case 8 : entity.setOut_date(MonitorResultUtil.objectToDate(value)); break;
                            //结算日期
                            case 9 : entity.setPay_date(MonitorResultUtil.objectToDate(value)); break;
                            //住院天数
                            case 10 : entity.setIn_hosp_days(Integer.parseInt(value)); break;
                            // DRG分组编码
                            case 11 : entity.setDrg_group_code(value); break;
                            //DRG分组名称
                            case 12 : entity.setDrg_group_desc(value); break;
                            //诊断
                            case 13 : entity.setDiagnose(value); break;
                            //详细科室
                            case 14 : entity.setDetail_dep(value); break;
                            //科室
                            case 15 : entity.setDep(value); break;
                            //实际结算金额
                            case 16 : entity.setActu_settle_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //实际统筹申报金额
                            case 17 : entity.setActu_total_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //实际大额申报金额
                            case 18 : entity.setActu_over_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //实际退休补充申报金额
                            case 19 : entity.setActu_retiresupple_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //实际军残补充申报金额
                            case 20 : entity.setActu_armyassist_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            // 实际单位补充申报金额
                            case 21 : entity.setActu_unitadd_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //实际自付一金额
                            case 22 : entity.setActu_selfpay1_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //实际自付二金额
                            case 23 : entity.setActu_selfpay2_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //实际自付金额
                            case 24 : entity.setActu_selfpay_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //明细总金额
                            case 25 : entity.setDetail_total_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //西药费
                            case 26 : entity.setWest_med_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //中药费
                            case 27 : entity.setChin_med_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //检查费
                            case 28 : entity.setInspec_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //治疗费
                            case 29 : entity.setTreat_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //手术费
                            case 30 : entity.setOper_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            // 化验费
                            case 31 : entity.setLabor_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //材料费
                            case 32 : entity.setMater_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //其他
                            case 33 : entity.setOther_fee(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟DRG分组
                            case 34 : entity.setDrg_code(value); break;
                            //模拟drg分组名称
                            case 35 : entity.setDrg_desc(value); break;
                            //模拟结算总金额
                            case 36:entity.setSimu_pay_total_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value));
                            //DRG分组支付标准(DRG发生费用)
                            case 37 : entity.setDrg_group_pay_std(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //组外金额
                            case 38: entity.setGroup_out_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value));
                            //模拟统筹申报金额
                            case 39 : entity.setSimu_total_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟大额申报金额
                            case 40 : entity.setSimu_big_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟退休补充申报金额
                            case 41 : entity.setSimu_retire_assist_supple_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟军残补助申报金额
                            case 42 : entity.setSimu_army_assist_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟单位补充申报金额
                            case 43 : entity.setSimu_unitassist_decl_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟自付一金额
                            case 44 : entity.setSimu_selfpay1_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟自付二金额
                            case 45 : entity.setSimu_selfpay2_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                            //模拟自付金额
                            case 46 : entity.setSimu_slefpay_amount(MonitorResultUtil.objectToDouble(value==null?"0.00":value)); break;
                        }
                    }
                    
                    if(!StringUtils.hasLength(entity.getMr_no())){
                    	 message.append("第" + (i+1) +"行数据病案号为空，请检查<br> ");
                    }else if(entity.getIn_date()==null){
                    	message.append("第" + (i+1) +"行数据入院日期为空，请检查<br> ");
                    }else if(entity.getOut_date()==null){
                    	message.append("第" + (i+1) +"行数据出院日期为空，请检查<br> ");
                    }else{
                    	//个人应付费用计算
                    	double individual_pay_amount=entity.getSimu_selfpay1_amount()+entity.getSimu_selfpay2_amount()+entity.getSimu_slefpay_amount();
                    	
                    	
                    	//基金支付额计算
                    	double fund_pay_amount=entity.getGroup_out_amount()+entity.getSimu_total_decl_amount();
                    	//盈亏
                    	double profit=entity.getDrg_group_pay_std()-entity.getActu_settle_amount();
                    	
                    	entity.setProfit(profit);
                    	entity.setIndividual_pay(individual_pay_amount);
                    	entity.setFund_pay_amount(fund_pay_amount);
                    	
                    	 //主键拼接
                        SimpleDateFormat sDateFormat=new SimpleDateFormat("yyyy/MM/dd");
                        String	inDateStr=null;
                        String	outDateStr=null;
                        if(entity.getIn_date()!=null) {
                        	inDateStr=sDateFormat.format(entity.getIn_date());
                        }
                        if(entity.getOut_date()!=null) {
                        	outDateStr=sDateFormat.format(entity.getOut_date());
                        }	
                        String pMainIndex = entity.getMr_no()+"_"+outDateStr +"_"+inDateStr;
                        detail=pMainIndex;
                        if(inDateStr!=null&&outDateStr!=null&&entity.getMr_no()!=null) {
                        entity.setPmainindex(pMainIndex);
                        }
//                        根据出院科室描述查找出院科室编码
                        String depCode=Department.findDepCodeByName(entity.getDep());
                        if(depCode!=null&&StringUtils.hasLength(depCode)){
                            entity.setDep_code(depCode);
                        }else{
                        	entity.setDep_code(UUID.randomUUID().toString().replaceAll("-", ""));
                        }
                        
                        String detailDepCode=Department.findDepCodeByName(entity.getDetail_dep());
                        if(detailDepCode!=null&&StringUtils.hasLength(detailDepCode)){
                            entity.setDetail_dep_code(detailDepCode);
                        }else{
                        	entity.setDetail_dep_code(UUID.randomUUID().toString().replaceAll("-", ""));
                        }
                        //dto实体类提交
                        try {
                        	drgFeeMedinsApplication.saveDrgFeeMedinsDetail(entity);  
                        } catch (Exception e) {
                            message.append("更新第" + (i+1) +"行数据时报错，请检查<br> ");
                            stateInfo="1";
                            e.printStackTrace();
                        }
                    }
                }
            }
            stateInfo="1";
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        deleteDepCostFile(filePath) ;
    }
    return InvokeResult.success();
}
    /**
     * 删除指定路径的文件
     * @param filePath
     */
    private void deleteDepCostFile(String filePath) {  
         File file = new File(filePath);
         if(file.exists()&&file.isFile()){
             file.delete();
         }
         System.out.println(filePath + " 删除成功 ！");
    }
    /**读取Excel 工作簿
     * 
     * @param filePath
     * @param index
     * @return
     */
    private Sheet readExcelSheet(String filePath,int index) {  
        String extension=filePath.substring(filePath.lastIndexOf(".")).toLowerCase();//扩展名
        Workbook workbook=null;
        Sheet sheet=null;
        InputStream inputStream = null ;
        try {
            inputStream = new FileInputStream(filePath) ;
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        /**
         * 判断Excel版本，创建工作簿
         */
        try {
            if (extension.equals(".xls")) {
                workbook=new HSSFWorkbook(inputStream);
                inputStream.close();
            } else if (extension.equals(".xlsx")){
                workbook=new XSSFWorkbook(inputStream);
            } 
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //读取工作表
        if (extension.equals(".xls")) {
            sheet=(HSSFSheet) workbook.getSheetAt(index);
        } else if(extension.equals(".xlsx")){
            sheet=(XSSFSheet)workbook.getSheetAt(index);
        } 
        return sheet;
    }
    /**
     * 读取单元格数据
     * @param cell
     * @return
     */
    private String getCellValue(Cell cell) {  //123
        String cellValue = "";
        DataFormatter formatter = new DataFormatter();
        if (cell != null) {
            switch (cell.getCellType()) {
                case Cell.CELL_TYPE_NUMERIC:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        cellValue = formatter.formatCellValue(cell);
                    } else {
                        double value = cell.getNumericCellValue();
                        String str=String.valueOf(value);
                        if(str.indexOf("E")>0){
                            DecimalFormat format=new DecimalFormat("#");
                            format.applyPattern("#");
                            String cellinfo=format.format(value);
                            cellValue=cellinfo;
                        }else{
                            if(value==0.0){
                                value=0.00;
                                cellValue="0.00";
                            }else{
                                value=Double.parseDouble(value+"");
                                int intValue = (int) value;
                                cellValue = value - intValue == 0 ? String.valueOf(intValue) : value+"";
                            }
                        }
                    }
                    break;
                case Cell.CELL_TYPE_STRING:
                    cellValue = cell.getStringCellValue();
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    cellValue = String.valueOf(cell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    cellValue = String.valueOf(cell.getCellFormula());
                    break;
                case Cell.CELL_TYPE_BLANK:
                    cellValue = "";
                    break;
                case Cell.CELL_TYPE_ERROR:
                    cellValue = "";
                    break;
                default:
                    cellValue = cell.toString().trim();
                    break;
            }
        }
        return cellValue.trim();
    }
    /**
     * @methodname    :printProgress
     * @description   :打印循环的进度
     * @param         :total：总数，i：当前位置
     */
    private void printProgress(int total,int i) {
        percent=(float)i*100/(float)total;
        if(i>=total){percent=100f;}
        long perTime = (new Date().getTime()-mdStartTime)/i;//平均时间
        time = msChangeDesc((total-i)*perTime);//剩余时间
    }
    /**
     * 毫秒转时间描述
     * @param ms
     * @return
     */
    public static String msChangeDesc(long ms){
        long hour=ms/(1000*60*60);
        long minute=(ms%(1000*60*60))/(1000*60);
        long second=(ms%(1000*60))/(1000);
        String desc = "";
        if (hour>0) {
            desc+=hour+"小时";
        }
        if (minute>0) {
            desc+=minute+"分";
        }
        if (second>0) {
            desc+=second+"秒";
        }
        return desc;
    }
    /**
     * 获取后台数据处理进度和详情
     */
    @Override
    public InvokeResult uploadDrgFeeMedinsProgress() {
        /**
         * fileInfo-正在处理的文件
         * saveInfo-保存信息
         * dataInfo-数据信息
         * errorInfo-错误信息
         * stateInfo-状态
         * percent-百分比
         */
        DecimalFormat df = new DecimalFormat("##0.00");
        Map<String,Object> map=new HashMap<>();
        if(stateInfo=="1") {
            //message.setLength(0);
            message.append("解析文件完毕");
        }else if(stateInfo=="2"){ //excel数据为空
            map.put("msg", message);
            map.put("stateInfo", "1");
            map.put("percent", 100);
            map.put("detail", detail);
            map.put("time", time);
            return InvokeResult.success(map);
        }
        map.put("msg", message);
        map.put("stateInfo", stateInfo);
        map.put("percent", df.format(percent.floatValue()));
        map.put("detail", detail);
        map.put("time", time);
        return InvokeResult.success(map);
    }
    
    /**
     *  @Description：获取科室医保指标
     *  @Author：huangju
     *  @see com.dhcc.DRGsHosp.facade.DrgFeeMedinsFacade#getDepMedinsQuota(java.util.Date, java.util.Date)
     */
	@Override
	public List<Map<String, Object>> getDepMedinsQuota(IndexCalDTO dto) {
		dto.setDateFrom(DrgsIndex.formateDateFrom(dto.getDateFrom()));
		dto.setDateTo(DrgsIndex.formateDateTo(dto.getDateTo()));
	    List<Map<String, Object>> list=drgFeeMedinsApplication.getDepMedinsQuota(IndexCalAssembler.toEntity(dto));
		return list;
	}
	/**
	 * 
	 * @Description：出院病历数列表
	 * @Author：qiaoyilong
	 * @ClassName: getOutCases  
	 * @Date: 2018年12月19日 上午11:14:36  
	 * @Version：3.1.0 DHC.DRGs 
	 */
	@Override
	public List<Map<String, Object>> getOutCases(IndexCalDTO dto) {
		dto.setDateFrom(DrgsIndex.formateDateFrom(dto.getDateFrom()));
		dto.setDateTo(DrgsIndex.formateDateTo(dto.getDateTo()));
	    List<Map<String, Object>> list=drgFeeMedinsApplication.getOutCases(IndexCalAssembler.toEntity(dto));
		return list;
	}
	/**
	 *  @Description：获取科室医保下的病组指标
	 *  @Author：huangju
	 *  @see com.dhcc.DRGsHosp.facade.DrgFeeMedinsFacade#getDepUnderDrgsMedinsQuota(com.dhcc.DRGsHosp.facade.dto.IndexCalDTO)
	 */
	public List<Map<String,Object>> getDepUnderDrgsMedinsQuota(IndexCalDTO dto){
		dto.setDateFrom(DrgsIndex.formateDateFrom(dto.getDateFrom()));
		dto.setDateTo(DrgsIndex.formateDateTo(dto.getDateTo()));
		List<Map<String,Object>> list= drgFeeMedinsApplication.getDepUnderDrgsMedinsQuota(IndexCalAssembler.toEntity(dto));
		return list;
	}
	/**
	 * 
	 *  @Description：获得出院病历的分组的最新日期
	 *  @Author huangju 
	 */
	@Override
	public String getLatestDate() {
		return drgFeeMedinsApplication.getLatestDate();
	}
}
